package org.daymr.puzzle.tools;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;

import android.content.res.Resources;
import android.opengl.GLES20;
import android.util.Log;

/**
 * 着色器工具类
 * @author Ben
 * @date 2014年12月19日 下午11:26:35
 */
public class ShaderUtils {
	
	/**
	 * 加载指定类型的着色器
	 * @param shaderType 着色器类型：顶点着色器和片元着色器
	 * @param source 着色器的源码
	 * @return shader的id，若为0，则创建失败
	 */
	public static int loadShader(int shaderType, String source){
		int shader = GLES20.glCreateShader(shaderType);//创建一个shader，并返回其id。若id为0，则创建失败。
		if(shader!=0){//若创建成功
			GLES20.glShaderSource(shader, source);//加载着色器的源代码
			GLES20.glCompileShader(shader);//编译
			//下面是获取shader的编译情况
			int[] compiled = new int[1];
			GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
			if(compiled[0]==0){//若编译失败，报告错误，删除shader
				Log.e("GLES20_ERROR", "Could not compile shader "+shaderType +": "+
						GLES20.glGetShaderInfoLog(shader));
				GLES20.glDeleteShader(shader);//删除shader
			}
		}
		return shader;
	}
	
	/**
	 * 创建着色器程序
	 * @param vertexSource
	 * @param fragmentSource
	 * @return
	 */
	public static int createProgram(String vertexSource , String fragmentSource){
		//加载顶点着色器
		int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
		if(vertexShader==0)
			return 0;
		//加载片元着色器
		int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
		if(pixelShader==0)
			return 0;
		//创建程序
		int program = GLES20.glCreateProgram();
		if(program!=0){//若程序创建成功，则加入顶点着色器和片元着色器
			GLES20.glAttachShader(program, vertexShader);
			checkGLError("glAttachShader");
			GLES20.glAttachShader(program, pixelShader);
			checkGLError("glAttachShader");
			GLES20.glLinkProgram(program);//链接程序
			int[] linkStatus = new int[1];
			GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
			if(linkStatus[0]!=GLES20.GL_TRUE){//若链接失败，则报告错误，并删除程序
				Log.e("GLES20_ERROR", "Could not link program : "+
						GLES20.glGetProgramInfoLog(program));
				GLES20.glDeleteProgram(program);//删除program
				program = 0;
			}
		}
		return program;
	}
	
	/**
	 * 检查每一步操作是否有错误
	 * @param op
	 */
	public static void checkGLError(String op){
		int error;
		while((error=GLES20.glGetError())!=GLES20.GL_NO_ERROR){
			Log.e("GLES20_ERROR", op+": glError "+ error);
			throw new RuntimeException(op+": glError "+ error);
		}
	}
	
	/**
	 * 读取指定Assets目录下的文件的内容，返回一个字符串。
	 * @param fileName 文件名
	 * @param r 资源
	 * @return 字符串
	 */
	public static String loadFromAssetsFile(String fileName,Resources r){
		String result = null;
		InputStream is = null;
		try {
			is = r.getAssets().open(fileName);
			int b = 0;
			ByteArrayOutputStream baos = new ByteArrayOutputStream();
			while((b=is.read())!=-1){
				baos.write(b);
			}
			byte[] buffer = baos.toByteArray();
			baos.close();
			result = new String(buffer, "UTF-8");
			result.replaceAll("\\r\\n", "\n");
		} catch (IOException e) {
			e.printStackTrace();
		}finally{
			if(is!=null)
				try {
					is.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
		}
		return result;
	}

}
